import os
import pcap
import dpkt
import socket
import urllib

from struct import unpack,pack

URL_Malware_DNS = "https://nsgbot.googlecode.com/svn/wiki/Malware_DNS.wiki"

DNS_DIC = {}

dns_fd = "/tmp/nsgbot_dnsQ"

SIZE_OF_PPKT = 168

def read_db(url):
    file = urllib.urlopen(url)
    for index in file:
        temp = index.split("||")
        # check number of elements
        if len(temp) != 7:
            print "Error"
            continue
        # get element
        DNS_DIC[temp[2]] = temp[3]
        print temp[2], temp[3]

def read_dns():
    pipein = open(dns_fd, 'r')
    while 1:
        line = pipein.read(SIZE_OF_PPKT)
        parse_ppkt(line)

def parse_ppkt(ppkt):
    tv_sec = unpack('Q', ppkt[0:8])[0]
    tv_usec = unpack('Q', ppkt[8:16])[0]
    saddr = pcap.ntoa(unpack('i',ppkt[16:20])[0])
    daddr = pcap.ntoa(unpack('i',ppkt[20:24])[0])
    proto = unpack('H',ppkt[24:26])[0]
    sport = unpack('H',ppkt[26:28])[0]
    dport = unpack('H',ppkt[28:30])[0]

    tag = unpack('I',ppkt[164:168])[0]
    # get payload size
    payload_size = unpack('H',ppkt[160:162])[0]
    #print payload_size
    if payload_size > 128:
        print "Payload size is wrong!!", payload_size
        payload_size = 128
    payload = ppkt[30:30+payload_size]

    #print tag
    if payload_size >= 128:
        return

    if dport == 53:
        #print "%s(%s)-(%s)->%s(%s)" % (saddr, sport, proto, daddr, dport)
        dns = dpkt.dns.DNS(payload)
        if dns.qr == dpkt.dns.DNS_Q:
            #print dns.qd[0].name
            if DNS_DIC.has_key(dns.qd[0].name) == True:
                print saddr, daddr, dns.qd[0].name
        else:
            print "Wrong"
    elif sport == 53:
        # from DNS Server (answer packet)
        msg = dpkt.dns.DNS(payload)
        if msg.qr == dpkt.dns.DNS_A and msg.rcode == dpkt.dns.DNS_RCODE_NOERR and len(msg.an)>0:
            queried = ""
            if msg.qd[0].type == dpkt.dns.DNS_A:
                queried = queried + "%s (A)" % (msg.qd[0].name)
            if msg.qd[0].type == dpkt.dns.DNS_NS:
                queried = queried + "%s (NS)" % (msg.qd[0].name)
            if msg.qd[0].type == dpkt.dns.DNS_CNAME:
                queried = queried + "%s (CNAME)" % (msg.qd[0].name)
            if msg.qd[0].type == dpkt.dns.DNS_SOA:
                queried = queried + "%s (SOA)" % (msg.qd[0].name)
            if msg.qd[0].type == dpkt.dns.DNS_PTR:
                queried = queried + "%s (PTR)" % (msg.qd[0].name)
            if msg.qd[0].type == dpkt.dns.DNS_HINFO:
                queried = queried + "%s (HINFO)" % (msg.qd[0].name)
            if msg.qd[0].type == dpkt.dns.DNS_MX:
                queried = queried + "%s (MX)" % (msg.qd[0].name)
            if msg.qd[0].type == dpkt.dns.DNS_TXT:
                queried = queried + "%s (TXT)" % (msg.qd[0].name)
            if msg.qd[0].type == dpkt.dns.DNS_AAAA:
                queried = queried + "%s (AAAA)" % (msg.qd[0].name)
            if msg.qd[0].type == dpkt.dns.DNS_SRV:
                queried = queried + "%s (SRV)" % (msg.qd[0].name)

            answers = []
            for an in msg.an:
                if an.type == dpkt.dns.DNS_A:
                    answers.append("[A]" + socket.inet_ntoa(an.ip))
                elif an.type == dpkt.dns.DNS_PTR:
                    answers.append("[PTR]" + an.ptrname)
                elif an.type == dpkt.dns.DNS_NS:
                    answers.append("[NS]" + an.nsname)
                elif an.type == dpkt.dns.DNS_CNAME:
                    answers.append("[CNAME]"+an.cname)
                elif an.type == dpkt.dns.DNS_SOA:
                    answers.append(an.mname)
                    answers.append(an.rname)
                    answers.append(str(an.serial))
                    answers.append(str(an.refresh))
                    answers.append(str(an.retry))
                    answers.append(str(an.expire))
                    answers.append(str(an.minimum))
                elif an.type == dpkt.dns.DNS_HINFO:
                    answers.append(" ".join(an.text))
                elif an.type == dpkt.dns.DNS_MX:
                    answers.append(an.mxname)
                elif an.type == dpkt.dns.DNS_TXT:
                    answers.append(" ".join(an.text))
                elif an.type == dpkt.dns.DNS_AAAA:
                    answers.append(inet_ntop(AF_INET6,an.ip6))
                elif an.type == dpkt.dns.DNS_SRV:
                    # do something with SRV
                    pass
                else:
                    # un-handled type
                    answers.append("[Honeysnap: Undecoded response]")
                    continue

#                for item in answers:
#                    print "%s -> %s" % (queried, ",".join(answers))

read_db(URL_Malware_DNS)
read_dns()
